//+------------------------------------------------------------------+
//|                                                 WndContainer.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Wnd.h"                      // 基础控件基类（提供基础控件能力）
#include <Arrays/ArrayObj.h>            // 对象数组类（用于存储子控件）

//+------------------------------------------------------------------+
//| CWndContainer 类：MQL5 容器控件基类                                |
//| 核心能力：继承自 CWnd，扩展子控件管理功能，支持添加/删除子控件、      |
//|           统一处理子控件事件与状态，是面板、窗口等复合控件的父类     |
//| 适用场景：作为包含多个子控件的复合控件基类（如对话框、工具栏等），    |
//|           可直接实例化或作为父类扩展                                  |
//+------------------------------------------------------------------+
class CWndContainer : public CWnd
  {
private:
   CArrayObj         m_controls;            // 子控件容器（存储所有添加的子控件）

public:
   //----------------------------------------------------------------
   // 构造与析构函数
   //----------------------------------------------------------------
   /**
    * @brief 构造函数：初始化容器控件
    * @details 初始化子控件容器（CArrayObj），继承 CWnd 的基础属性
    */
                     CWndContainer(void);

   /**
    * @brief 析构函数：清理容器资源
    * @details 依赖 Destroy() 方法释放所有子控件
    */
                    ~CWndContainer(void);

   //----------------------------------------------------------------
   // 资源释放：销毁容器及所有子控件
   //----------------------------------------------------------------
   /**
    * @brief 销毁容器并释放所有子控件资源
    * @param reason [in] 销毁原因（默认 0，预留参数）
    * @details 遍历所有子控件并调用其 Destroy() 方法，最后清空子控件容器
    */
   virtual void      Destroy(const int reason=0);

   //----------------------------------------------------------------
   // 事件处理：分发事件到子控件
   //----------------------------------------------------------------
   /**
    * @brief 处理图表事件（分发到子控件）
    * @param id [in] 事件ID（如 CHARTEVENT_MOUSE_MOVE 表示鼠标移动）
    * @param lparam [in] 长整数参数（事件相关数据）
    * @param dparam [in] 双精度参数（事件相关数据）
    * @param sparam [in] 字符串参数（事件相关数据）
    * @return bool - 处理结果：true=事件被某子控件处理，false=未处理
    * @note 优先处理拖拽对象事件，再按逆序（顶层控件优先）分发到子控件
    */
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

   /**
    * @brief 处理鼠标事件（分发到子控件）
    * @param x [in] 鼠标X坐标（像素）
    * @param y [in] 鼠标Y坐标（像素）
    * @param flags [in] 鼠标按键状态（见 MOUSE_* 常量）
    * @return bool - 处理结果：true=事件被某子控件处理，false=未处理
    * @note 优先处理拖拽对象事件，再按逆序（顶层控件优先）分发到子控件，
    *       若子控件均未处理，则调用父类 CWnd 的鼠标事件处理
    */
   virtual bool      OnMouseEvent(const int x,const int y,const int flags);

   //----------------------------------------------------------------
   // 子控件访问：获取子控件数量及指定子控件
   //----------------------------------------------------------------
   /**
    * @brief 获取子控件总数
    * @return int - 子控件数量（m_controls.Total()）
    */
   int               ControlsTotal(void)               const;

   /**
    * @brief 获取指定索引的子控件
    * @param ind [in] 子控件索引（0 开始，逆序对应显示层级）
    * @return CWnd* - 子控件指针（NULL 表示索引无效）
    */
   CWnd*             Control(const int ind)            const;

   /**
    * @brief 根据ID查找子控件（包括嵌套容器）
    * @param id [in] 目标控件ID
    * @return CWnd* - 找到的控件指针（NULL 表示未找到）
    * @note 先检查自身ID，再递归查找所有子控件及其子容器
    */
   virtual CWnd*     ControlFind(const long id);

   //----------------------------------------------------------------
   // 鼠标焦点管理：取消容器及所有子控件的焦点
   //----------------------------------------------------------------
   /**
    * @brief 取消容器及所有子控件的鼠标焦点（激活状态）
    * @param id [in] 新焦点控件ID（默认 -1 表示无新焦点）
    * @return bool - 操作结果：true=成功（容器及子控件均已失焦），false=失败
    */
   virtual bool      MouseFocusKill(const long id=-1);

   //----------------------------------------------------------------
   // 子控件添加：将子控件加入容器
   //----------------------------------------------------------------
   /**
    * @brief 添加子控件（通过指针）
    * @param control [in] 子控件指针（非空）
    * @return bool - 添加结果：true=成功，false=失败（指针为空或添加失败）
    * @note 自动调整子控件坐标（相对容器偏移），同步容器的可见性和启用状态到子控件
    */
   bool              Add(CWnd *control);

   /**
    * @brief 添加子控件（通过引用）
    * @param control [in] 子控件引用
    * @return bool - 添加结果：true=成功，false=失败
    * @note 内部转换为指针调用 Add(CWnd *control)
    */
   bool              Add(CWnd &control);

   //----------------------------------------------------------------
   // 子控件删除：从容器中移除子控件
   //----------------------------------------------------------------
   /**
    * @brief 从容器中删除子控件（通过指针）
    * @param control [in] 要删除的子控件指针
    * @return bool - 删除结果：true=成功，false=失败（未找到或删除失败）
    */
   bool              Delete(CWnd *control);

   /**
    * @brief 从容器中删除子控件（通过引用）
    * @param control [in] 要删除的子控件引用
    * @return bool - 删除结果：true=成功，false=失败
    * @note 内部转换为指针调用 Delete(CWnd *control)
    */
   bool              Delete(CWnd &control);

   //----------------------------------------------------------------
   // 几何布局：移动容器及所有子控件
   //----------------------------------------------------------------
   /**
    * @brief 绝对移动容器及所有子控件（将左上角移至指定坐标）
    * @param x [in] 目标左上角X坐标（像素）
    * @param y [in] 目标左上角Y坐标（像素）
    * @return bool - 移动结果：true=成功，false=失败
    * @note 内部通过计算偏移量调用 Shift() 实现
    */
   virtual bool      Move(const int x,const int y);

   /**
    * @brief 绝对移动容器及所有子控件（通过点结构）
    * @param point [in] 目标左上角点（CPoint 结构）
    * @return bool - 移动结果：true=成功，false=失败
    */
   virtual bool      Move(const CPoint &point);

   /**
    * @brief 相对移动容器及所有子控件（从当前位置偏移）
    * @param dx [in] X轴偏移量（像素，正数向右）
    * @param dy [in] Y轴偏移量（像素，正数向下）
    * @return bool - 移动结果：true=成功（容器及所有子控件均移动），false=失败
    */
   virtual bool      Shift(const int dx,const int dy);

   //----------------------------------------------------------------
   // 控件ID：设置容器及所有子控件的ID
   //----------------------------------------------------------------
   /**
    * @brief 设置容器及所有子控件的ID（确保唯一性）
    * @param id [in] 容器的基础ID（子控件ID在此基础上递增）
    * @return long - 已使用的ID总数（容器+所有子控件占用的ID数量）
    */
   virtual long      Id(const long id);

   /**
    * @brief 获取容器的ID
    * @return long - 容器ID（继承自 CWnd 的 m_id）
    */
   long              Id(void) const;

   //----------------------------------------------------------------
   // 控件状态：统一设置容器及所有子控件的状态
   //----------------------------------------------------------------
   /**
    * @brief 启用容器及所有子控件（使其可响应事件）
    * @return bool - 操作结果：true=成功，false=失败
    * @note 先启用所有子控件，再启用容器自身
    */
   virtual bool      Enable(void);

   /**
    * @brief 禁用容器及所有子控件（使其不响应事件）
    * @return bool - 操作结果：true=成功，false=失败
    * @note 先禁用所有子控件，再禁用容器自身
    */
   virtual bool      Disable(void);

   /**
    * @brief 显示容器及所有子控件
    * @return bool - 操作结果：true=成功，false=失败
    * @note 先显示所有子控件，再显示容器自身
    */
   virtual bool      Show(void);

   /**
    * @brief 隐藏容器及所有子控件
    * @return bool - 操作结果：true=成功，false=失败
    * @note 先隐藏所有子控件，再隐藏容器自身
    */
   virtual bool      Hide(void);

   //----------------------------------------------------------------
   // 文件操作：保存/加载容器及子控件状态
   //----------------------------------------------------------------
   /**
    * @brief 保存容器及所有子控件的状态到文件
    * @param file_handle [in] 文件句柄（已打开的可写文件）
    * @return bool - 保存结果：true=所有控件保存成功，false=至少一个控件保存失败
    */
   virtual bool      Save(const int file_handle);

   /**
    * @brief 从文件加载容器及所有子控件的状态
    * @param file_handle [in] 文件句柄（已打开的可读文件）
    * @return bool - 加载结果：true=所有控件加载成功，false=至少一个控件加载失败
    */
   virtual bool      Load(const int file_handle);

protected:
   //----------------------------------------------------------------
   // 内部事件回调：子类可重写以扩展功能
   //----------------------------------------------------------------
   /**
    * @brief 容器尺寸变化事件回调
    * @return bool - 处理结果：true=成功（所有子控件已按容器新尺寸对齐），false=失败
    * @note 调用所有子控件的 Align() 方法，使其适应容器新尺寸
    */
   virtual bool      OnResize(void);

   /**
    * @brief 容器激活事件回调
    * @return bool - 处理结果：true=成功（容器及所有子控件已激活），false=失败
    * @note 先激活容器自身，再激活所有子控件
    */
   virtual bool      OnActivate(void);

   /**
    * @brief 容器取消激活事件回调
    * @return bool - 处理结果：true=成功（容器及所有子控件已取消激活），false=失败
    * @note 先取消激活容器自身，再取消激活所有子控件
    */
   virtual bool      OnDeactivate(void);
  };
//+------------------------------------------------------------------+